﻿// ***********************************************************************
// 程 序 集  : HdhNetQuery
// 建立时间  : 2025-10
// 类库说明  ：泛型实体与数据转换的操作类
// 个人网站  ：http://www.hdhcms.com 
// ***********************************************************************
// <copyright>
//     Copyright by He DongHua(何冬华) All, QQ群:876705805 QQ:664627440 Email:664627440@qq.com
// </copyright>
// 如果要使用当前代码，请保存这些信息
// ***********************************************************************
using System.Data;
using System.Reflection;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;

namespace HdhNetQuery
{
    /// <summary>
    /// 泛型实体的数据库操作
    /// </summary>
    public static class HdhcmsGenericEntity
    {
        #region 实体泛型操作类
        /// <summary>
        /// 实体方法返回JSON字符串
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="hre">实体对象</param>
        /// <returns></returns>
        public static string EntityToJsonString<T>(T hre)
        {
            string strBack = "";
            if (hre != null)
            {
                var JsonOptions = new JsonSerializerOptions
                {
                    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
                    WriteIndented = true
                };
                strBack = JsonSerializer.Serialize(hre, JsonOptions);
            }
            return strBack;
        }
        /// <summary>
        /// json字符串返回实体
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="str">JSON字符串</param>
        /// <returns>返回实体对象</returns>
        /// <exception cref="Exception"></exception>
        public static T? JsonStringToEntity<T>(string str) where T : new()
        {
            T? hre = new T();
            try
            {
                if (!string.IsNullOrEmpty(str))
                {
                    hre = JsonSerializer.Deserialize<T>(str);
                }
                return hre;
            }
            catch (Exception ex)
            {
                //throw new Exception($"返回实体错误！详细错误：{ex.Message}");
                return default;
            }
        }
        /// <summary>
        /// 将DataRow行数据赋值给Model
        /// </summary>
        /// <typeparam name="T">实体名</typeparam>
        /// <param name="row">实体对应的DataRow</param>
        /// <returns></returns>
        public static T DataRowToModel<T>(DataRow row) where T : new()
        {
            //初始化
            T t = new T();
            //得到类型
            Type type = t.GetType();
            //属性集合
            PropertyInfo[] ps = type.GetProperties();
            //赋值、格式转换
            foreach (PropertyInfo p in ps)
            {
                if (row.Table.Columns.Contains(p.Name))
                {
                    #region 包含当前字段才处理
                    var _data = row[p.Name];
                    if (_data != null && _data != DBNull.Value)//非空
                    {
                        if (p.PropertyType == typeof(System.Nullable<System.DateTime>))//空时间
                            p.SetValue(t, DateTime.Parse(_data.ToString()), null);
                        else if (p.PropertyType == typeof(System.Nullable<System.Decimal>))//空Decimal
                            p.SetValue(t, Decimal.Parse(_data.ToString()), null);
                        else if (p.PropertyType == typeof(System.Nullable<System.Int32>))//空Decimal
                            p.SetValue(t, Int32.Parse(_data.ToString()), null);
                        else if (p.PropertyType.IsClass
                        && p.PropertyType != typeof(string) //IsClass=true
                        && p.PropertyType != typeof(Byte[]) //IsClass=true
                        && p.PropertyType != typeof(Object) //IsClass=true
                        )  //判断是否为自定义类
                        {
                            if (_data != null && _data != DBNull.Value)
                            {
                                // 尝试将字符串转换为实际类型
                                string fullName = $"{p.PropertyType.FullName}, {p.PropertyType.Assembly.GetName().Name}";
                                Type? targetType = Type.GetType(fullName);
                                if (targetType != null)
                                {
                                    // 创建目标类型的实例（假设可以通过默认构造函数创建）
                                    object? propertyValue = Activator.CreateInstance(p.PropertyType);
                                    //json数据
                                    object? objJson = JsonSerializer.Deserialize(_data.ToString(), targetType);
                                    if (objJson != null)
                                    {
                                        // 尝试将值转换为对象类型标类型
                                        propertyValue = Convert.ChangeType(objJson, targetType);
                                    }
                                    // 设置属性值
                                    p.SetValue(t, propertyValue);
                                }
                            }
                        }
                        else
                            p.SetValue(t, Convert.ChangeType(_data, p.PropertyType), null);
                    }
                    #endregion
                }
            }
            return t;
        }
        /// <summary>
        /// 将DataTable数据赋值给List集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static List<T>? DataToModel<T>(DataTable dt) where T : new()
        {
            List<T>? list = null;
            T m = new T();
            if (dt != null)
            {
                list = new List<T>();
                foreach (DataRow dr in dt.Rows)
                {
                    m = DataRowToModel<T>(dr);
                    list.Add(m);
                }
            }
            return list;
        }
        /// <summary>
        /// 对象转实体
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public static T? ObjectToModel<T>(object data)
        {
            try
            {
                T reBack = (T)data;
                return reBack;
            }
            catch
            {
                return default;
            }
        }

        /// <summary>
        /// 返回查询语句多条件的拼接，
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="keyField">插入前要核对数据是否重复的字段</param>
        /// <param name="strAndOr">核对字段的条件拼接处理，是用 and 还是 or</param>
        /// <returns>比如： a=b and cd=d </returns>
        public static string GetQueryConditionWhere<T>(T t, string keyField = "", string strAndOr = "or") where T : new()
        {
            //属性集合
            string? name=null;
            Type type = t.GetType();
            PropertyInfo[] ps = type.GetProperties();
            string[] keyFieldArray = keyField.Split('|');
            StringBuilder sbTouj = new StringBuilder();
            foreach (PropertyInfo p in ps)
            {
                foreach (string strItem in keyFieldArray)
                {
                    if (strItem.Split(',').Contains(p.Name))
                    {
                        PropertyInfo? pi = type.GetProperty(p.Name);
                        if (pi != null)
                        {
                            var a = pi.GetValue(t);
                            if (a != null)
                            {
                                name = a.ToString();
                                string ToLower = "";
                                int DataType = HdhcmsUniversalFunction.GetDataType();
                                switch (DataType)
                                {
                                    case (int)HdhcmsEnumClass.DataType.PostgreSql:
                                        ToLower = "lower";
                                        break;
                                    case (int)HdhcmsEnumClass.DataType.Mssql:
                                        ToLower = ""; //大小写不敏感
                                        break;
                                    case (int)HdhcmsEnumClass.DataType.MySql:
                                        ToLower = "LOWER";
                                        break;
                                    default: //0=Sqlite  Mssql MySql PostgreSql
                                        ToLower = "lower";
                                        break;
                                }

                                if (strItem.IndexOf(",") > 0)
                                {
                                    #region 有包含字段属性时的处理及字段及格式定义
                                    //有包含属性比如  "id,int"，说明id这个字段是int的类型
                                    string[] lx = strItem.Split(',');
                                    if (lx[1].ToLower().Equals("int"))
                                    {
                                        sbTouj.Append(string.Format("" + strAndOr + "  " + lx[0] + "='{0}'  ", name.ToLower()));
                                    }
                                    else if (lx[1].ToLower().Equals("date"))
                                    {
                                        sbTouj.Append(string.Format("" + strAndOr + "  " + lx[0] + "='{0}'  ", name.ToLower()));
                                    }
                                    else if (lx[1].ToLower().Equals("byte"))
                                    {
                                        sbTouj.Append(string.Format("" + strAndOr + "  " + lx[0] + "='{0}'  ", name.ToLower()));
                                    }
                                    else
                                    {
                                        sbTouj.Append(string.Format("" + strAndOr + "  " + ToLower + @"(" + lx[0] + ")='{0}'  ", name.ToLower().Replace("'", "''")));
                                    }
                                    #endregion
                                }
                                else
                                {
                                    #region 无字段属性的处理 
                                    //未包含属性的统一按字符串处理，比如："name"
                                    sbTouj.Append(string.Format("" + strAndOr + "  " + ToLower + @"(" + strItem + ")='{0}'  ", name.ToLower().Replace("'", "''")));
                                    #endregion
                                }
                            }
                        }
                    }
                }
            }
            string where = "";
            if (sbTouj != null)
            {
                where = sbTouj.ToString().Remove(0, strAndOr.Length);
            }
            return where;
        }

        /// <summary>
        /// 返回查询语句,如何要拼接条件可以通过GetQueryConditionWhere方法获取条件后，再做参数传进来
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="strWhere">传条件时不要带 where 函数会自己加</param>
        /// <param name="strOrder">排序字段及方式</param>
        /// <returns></returns>
        public static string GetQuerySql<T>(string strWhere, string strOrder = " order by id desc") where T : new()
        {
            StringBuilder hdhSql = new StringBuilder();
            #region 获取MODEL的字段
            T t = new T();
            Type type = t.GetType();
            string ModelName = type.Name;
            PropertyInfo[] ps = type.GetProperties();
            StringBuilder sbField = new StringBuilder();
            foreach (PropertyInfo pi in ps)
            {
                sbField.Append("," + pi.Name);
            }
            #endregion

            hdhSql.Append("select  " + sbField.ToString().Remove(0, 1));
            hdhSql.Append(" FROM  " + ModelName);
            if (strWhere.Trim() != "")
            {
                strWhere = strWhere.TrimStart().ToLower();
                if (strWhere.Contains("where "))
                {
                    hdhSql.Append(strWhere);
                }
                else
                {
                    hdhSql.Append(" where " + strWhere);
                }
            }
            hdhSql.Append(strOrder);
            return hdhSql.ToString();
        }
        #endregion

    }
}
